package com.zj.executor;

import com.zj.binding.MapperRegistry;
import com.zj.mapping.BoundSql;
import com.zj.mapping.MappedStatement;
import com.zj.utils.Configuration;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;

public class FastResultSetHandler implements ResultSetHandler {
    protected final Executor executor;
    protected final Configuration configuration;
    protected final MappedStatement mappedStatement;
    protected final ParameterHandler parameterHandler;
    protected final BoundSql boundSql;
//    protected final TypeHandlerRegistry typeHandlerRegistry;

    protected Map<String, String> colomnToFieldMap = new HashMap<>();
    protected  Class clazz;

    public FastResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, BoundSql boundSql) {
        this.executor = executor;
        this.configuration = mappedStatement.getConfiguration();
        this.mappedStatement = mappedStatement;
        this.parameterHandler = parameterHandler;
        this.boundSql = boundSql;
//        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
        setResultTypeAndMap();
    }


    public List<Object> handleResultSets(Statement stmt) throws SQLException {
        final List<Object> multipleResults = new ArrayList<Object>();
//        final List<ResultMap> resultMaps = mappedStatement.getResultMaps();
//        int resultMapCount = resultMaps.size();
        int resultSetCount = 0;
        ResultSet rs = stmt.getResultSet();

        boolean isWrap=isWrapClass(clazz);
        while(rs.next()){
            ResultSetMetaData metadata = rs.getMetaData();
            int count = metadata.getColumnCount();
            if (!isWrap&& count > 1) {
                throw new RuntimeException("查询列数与结果类型不匹配");
            }
            multipleResults.add(isWrap?putResultToPOJOType(rs,metadata):putResultToSimpleType(rs));
        }
        return multipleResults;
    }

    private void setResultTypeAndMap(){
        this.clazz =mappedStatement.getResultType();
        Field[] fields = clazz.getDeclaredFields();
        //用map后就不用强制属性名和列名完全一致。
        for (int i = 0; i < fields.length; i++) {
            colomnToFieldMap.put(clazz.getName() + "." + fields[i].getName().toLowerCase(), fields[i].getName());
        }
    }

    public boolean isWrapClass(Class clz) {
        if (clz.equals(String.class) || clz.equals(Date.class)) {
            return false;
        }
        return !clz.isPrimitive();
    }

    public Object putResultToSimpleType(ResultSet rs) {
        try {
            return rs.getObject( 1);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Object putResultToPOJOType(ResultSet rs, ResultSetMetaData metadata) {
        try {
            Object bean = clazz.newInstance();
            for (int i = 0; i < metadata.getColumnCount(); i++) {
                String coulmnName = metadata.getColumnName(i + 1).toLowerCase();//得到每列的列名
                Object coulmnData = rs.getObject(i + 1);
                String mapKey=clazz.getName() + "." + coulmnName.toLowerCase();
                String field = colomnToFieldMap.get(mapKey);
                if (field != null) {
                    Field f = clazz.getDeclaredField(field);//反射出类上列名对应的属性
                    f.setAccessible(true);
                    f.set(bean, coulmnData);
                }
            }
            return bean;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
